﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using
Koolwired.Imap;
using anmar.SharpMimeTools;
using System.IO;
using System.Text.RegularExpressions;

namespace Mailer.Utilities.MailPoller
{
	public class Poller
	{
		public string Mailserver { get; set; }
		public string Username { get; set; }
		public string Password { get; set; }
		// public List<string> Mails { get; set; }
		public List<MailID> Rejects { get; set; }
		public int Limit { get; set; }

		public Poller()
		{
			Limit = 5;
			Mailserver = "";
			Username = "";
			Password = "";
			// Mails = new List<string>();
			Rejects = new List<MailID>();
		}

		public bool PollOnce(int limit, bool allowdelete)
		{
			Logger.Debug(typeof(Poller), "Polling server " + Mailserver + ", limit=" + limit + ", allowdelete=" + allowdelete + " (as " + Username + ")");
			Rejects.Clear();

			//			using (
			ImapConnect conn = new ImapConnect();
			// )
			//			{
			conn.Hostname = Mailserver;
			conn.LoginType = LoginType.LOGIN;
			conn.Open();

			ImapAuthenticate auth = new ImapAuthenticate(conn, Username, Password);
			//	{
			auth.Login();

			ImapCommand cmd = new ImapCommand(conn);

			/*
			ImapMailbox mbox = cmd.Select("INBOX");
			// mbox = cmd.Fetch(mbox);

			// mbox.Messages[0].
			//	string raw = cmd.FetchRaw(mbox, 0, 0);
			//	Logger.Debug(typeof(Poller), "raw: " + raw);

			conn.Write("FETCH 1 full\r\n");
			string res = "";
			string tmp = "";
			do
			{
				tmp = conn.Read();
				Logger.Debug(typeof(Poller), "tmp: " + tmp);
				Console.WriteLine(tmp);
				res += tmp;
			}
			while (!(ImapCommand.IsResponseEnd(tmp)));

			Logger.Debug(typeof(Poller), "res: " + res);
			Console.WriteLine(res);
			*/









			ImapMailbox mbox = cmd.Select("INBOX");
			mbox = cmd.Fetch(mbox);

			Logger.Debug(typeof(Poller), mbox.Messages.Count + " messages in inbox.");
			if (mbox.Messages.Count > 0)
			{
				for (int j = 0; j < Math.Min(limit, mbox.Messages.Count); j++)
				{
					string nmailerid = "";
					bool maybe_failure = false;

					ImapMailboxMessage m = mbox.Messages[j];

					Logger.Debug(typeof(Poller), m.ToString());
					Logger.Debug(typeof(Poller), "subject: " + m.Subject);

					foreach (string s in FailureNotices)
					{
						if (Regex.IsMatch(m.Subject, s, RegexOptions.IgnoreCase))
							maybe_failure = true;
					}

					cmd.FetchBodyStructure(m);

					// Logger.Debug(typeof(Poller), "text: " + m.Text);
					// Logger.Debug(typeof(Poller), "bodyparts: " + m.BodyParts.Count);

					if (m.BodyParts != null)
					{
						for (int k = 0; k < m.BodyParts.Count; k++)
						{
							cmd.FetchBodyPart(m, k);

							// m.BodyParts[k].BodyType

							string bod = m.BodyParts[k].Data;
							// m.BodyParts[k].
							Logger.Debug(typeof(Poller), "bodypart[]: " + bod);

							Match m1 = Regex.Match(bod, "[\\s^]+X\\-NMailer\\-ID:[\\s]+([a-z0-9r\\.\\-]+)[\\s$]+", RegexOptions.IgnoreCase | RegexOptions.Multiline);
							if (m1.Groups.Count > 1)
							{
								Logger.Debug(typeof(Poller), "m1.Value=" + m1.Groups[1].Value);
								nmailerid = m1.Groups[1].Value;
							}
						}
					}


					Logger.Debug(typeof(Poller), "nmailer-id: " + nmailerid);
					Logger.Debug(typeof(Poller), "maybe_failure: " + maybe_failure);

					if (maybe_failure)
					{
						if (nmailerid != "")
						{
							MailID mail = MailID.Parse(nmailerid);
							if (mail != null)
								Rejects.Add(mail);

							if (allowdelete)
								cmd.SetDeleted(m.ID, true);
						}
					}

					// cmd = new ImapCommand(conn);
					// 	cmd.Expunge();
				}
			}

			if (allowdelete)
				cmd.Expunge();

			// mbox.f

			auth.Logout();
			//	}
			conn.Close();
			//}



			Logger.Debug(typeof(Poller), "Got " + Rejects.Count + " rejects.");
			return (Rejects.Count > 0);
		}

		public static List<string> FailureNotices
		{
			get
			{
				List<string> ret = new List<string>();
				//	ret.Add("Delayed message");
				ret.Add("delivery error");
				ret.Add("delivery fail");
				ret.Add("delivery has failed");
				ret.Add("delivery notification");
				ret.Add("delivery problem");
				ret.Add("delivery report");
				ret.Add("delivery status");
				ret.Add("delivery status notification \\(failure\\)");
				ret.Add("Error delivering");
				ret.Add("Failed mail");
				ret.Add("Failure delivery");
				ret.Add("Failure notice");
				ret.Add("Mail delivery failed");
				ret.Add("Mail Error");
				ret.Add("Mail failed");
				ret.Add("Mail rejected");
				ret.Add("Mail Retornado");
				ret.Add("Mail status report");
				ret.Add("Mail System Error");
				ret.Add("Message not deliverable");
				ret.Add("Message Returned");
				ret.Add("No such user");
				ret.Add("no user");
				ret.Add("Non remis");
				ret.Add("Nondeliverable mail");
				ret.Add("Non-deliverable mail");
				ret.Add("Non-delivery notification");
				ret.Add("Notification .+de remise");
				ret.Add("Onbestelbaar");
				ret.Add("rejected by system");
				ret.Add("Rejected Mail");
				ret.Add("Return Receipt");
				ret.Add("Returned Mail");
				ret.Add("Unable to deliver");
				ret.Add("Undeliverable");
				ret.Add("Undelivered");
				ret.Add("Unrecognized recipient");
				ret.Add("Unzustellbar");
				ret.Add("User unknown");
				ret.Add("Zustellungsfehler");
				return ret;
			}
		}


	}
}
